"""
Copyright (c) 2022 Huawei Technologies Co.,Ltd.

openGauss is licensed under Mulan PSL v2.
You can use this software according to the terms and conditions of the Mulan PSL v2.
You may obtain a copy of Mulan PSL v2 at:

          http://license.coscl.org.cn/MulanPSL2

THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
See the Mulan PSL v2 for more details.
"""
"""
Case Type   : 表文件
Case Name   : 表文件没有权限
Create At   : 2020/07/01
Owner       : @wan005
Description :
    1.创建表
    2.查找表文件名称打开表数据文件，删除表文件权限
    3.向表中插入、查询数据
    4.恢复表文件权限
    5.插入数据，并查询
Expect      :
    1.创建表成功
    2.查找表文件名称打开表数据文件，删除表文件权限成功
    3.向表中插入、查询数据失败，permission denied
    4.恢复表文件权限成功
    5.插入数据，并查询，结果正确
History     :
    Modified by @peilinqian 2021/10/19: 优化用例逻辑，删除权限后不进行重启，仅保证恢复权限后插入数据成功
    Modified by @peilinqian 2022/3/15: 优化用例，保证权限修改后，避免缓冲区影响，permission权限稳定报错
"""

import os
import unittest

from testcase.utils.Common import Common
from testcase.utils.CommonSH import CommonSH
from testcase.utils.CommonSH import RestartDbCluster
from testcase.utils.Constant import Constant
from testcase.utils.Logger import Logger
from yat.test import Node
from yat.test import macro


class ChmodTablefile(unittest.TestCase):
    nodes_tuple = ('PrimaryDbUser', 'Standby1DbUser', 'Standby2DbUser')

    @RestartDbCluster(*nodes_tuple)
    def setUp(self):
        self.log = Logger()
        self.log.info(f'----{os.path.basename(__file__)}:初始化----')
        self.dn_path = macro.DB_INSTANCE_PATH
        self.dbUserNode = Node(node='dbuser')
        self.com = Common()
        self.constant = Constant()
        self.t_name = 'bt_reliability_dbsys064'
        self.rmpath = ''
        self.table_file = ''
        self.pri_sh = CommonSH()

    def test_rename_tablefile(self):
        step_txt = '----step1:创建表，并写入数据; expect:创建成功----'
        self.log.info(step_txt)
        sql = f'drop table if exists {self.t_name}; ' \
            f'create table {self.t_name}(id int); ' \
            f'insert into {self.t_name} values(generate_series(1,100));'
        result = self.pri_sh.executDbSql(sql)
        self.log.info(result)
        self.assertIn('INSERT', result, '执行失败:' + step_txt)

        step_txt = '----step2:查找表文件名称打开表数据文件，删除表文件权限; expect:删除权限成功----'
        self.log.info(step_txt)
        self.log.info('----查询oid----')
        sql_cmd = f"select oid from pg_class where relname='{self.t_name}';"
        self.log.info(sql_cmd)
        result = self.pri_sh.executDbSql(sql_cmd)
        self.log.info(result)
        oid = result.splitlines()[-2]
        self.log.info(oid)
        self.log.info('----通过oid查询文件位置----')
        sql_cmd = f"select pg_relation_filepath({oid}::regclass);"
        self.log.info(sql_cmd)
        result = self.pri_sh.executDbSql(sql_cmd)
        self.log.info(result)
        self.rmpath = result.splitlines()[-2].strip()
        self.log.info(self.rmpath)
        self.table_file = os.path.join(self.dn_path, self.rmpath)

        self.log.info('----修改表文件权限----')
        rm_cmd = f'chmod 000 {self.table_file}'
        self.log.info(rm_cmd)
        msg = self.dbUserNode.sh(rm_cmd).result()
        self.log.info(msg)
        ls_cmd = f'ls -l {self.table_file}'
        self.log.info(ls_cmd)
        msg = self.dbUserNode.sh(ls_cmd).result()
        self.log.info(msg)

        step_txt = '----step3:向表中插入、查询数据; expect:插入失败permission denied----'
        self.log.info(step_txt)
        sql_cmd = f'insert into {self.t_name} values ' \
            f'(generate_series(1,10000));'
        self.log.info(sql_cmd)
        result = self.pri_sh.executDbSql(sql_cmd)
        self.log.info(result)
        self.assertIn(self.constant.PERMISSION_DENY_MSG, result,
                      '执行失败:' + step_txt)

        sql_cmd = f'select count(*) from {self.t_name};'
        self.log.info(sql_cmd)
        result = self.pri_sh.executDbSql(sql_cmd)
        self.log.info(result)
        self.assertIn(self.constant.PERMISSION_DENY_MSG, result,
                      '执行失败:' + step_txt)

        self.log.info('----查询主备状态----')
        self.pri_sh.getDbClusterStatus('status')

        step_txt = '----step4:恢复表文件权限; expect:恢复成功----'
        self.log.info(step_txt)
        rm_cmd = f'chmod 700 {self.table_file}'
        self.log.info(rm_cmd)
        msg = self.dbUserNode.sh(rm_cmd).result()
        self.log.info(msg)
        ls_cmd = f'ls -l {self.table_file}'
        self.log.info(ls_cmd)
        msg = self.dbUserNode.sh(ls_cmd).result()
        self.log.info(msg)

        step_txt = '----step5:插入数据，并查询; expect:插入成功、结果正确----'
        self.log.info(step_txt)
        sql_cmd = f'insert into {self.t_name} values(1);'
        self.log.info(sql_cmd)
        result = self.pri_sh.executDbSql(sql_cmd)
        self.log.info(result)
        self.assertIn('INSERT', result, '执行失败:' + step_txt)

        sql_cmd = f'select count(*) from {self.t_name};'
        self.log.info(sql_cmd)
        result = self.pri_sh.executDbSql(sql_cmd)
        self.log.info(result)
        row = int(result.splitlines()[-2].strip())
        self.assertEqual(101, row, '执行失败:' + step_txt)

    def tearDown(self):
        self.log.info('----this is teardown----')
        self.log.info('----recover permmission----')
        if self.rmpath != '':
            rm_cmd = f'chmod 700 {self.table_file}'
            self.log.info(rm_cmd)
            msg = self.dbUserNode.sh(rm_cmd).result()
            self.log.info(msg)
            ls_cmd = f'ls -l {self.table_file}'
            self.log.info(ls_cmd)
            msg = self.dbUserNode.sh(ls_cmd).result()
            self.log.info(msg)
        step_txt = '----drop table----'
        self.log.info(step_txt)
        sql = f'drop table if exists {self.t_name};'
        result = self.pri_sh.executDbSql(sql)
        self.log.info(result)

        self.log.info('----teardown断言----')
        self.log.info(step_txt)
        self.assertIn(self.constant.DROP_TABLE_SUCCESS, result,
                      '执行失败:' + step_txt)

        self.log.info(f'----{os.path.basename(__file__)}:执行完毕----')
